其他
数据治理 | 从“今天中午吃什么”中学习Python文本相似度计算
目录
一、前言
二、用 Python 计算文本相似度
编辑距离
杰卡德距离
余弦相似度
TF-IDF
基于近义词
三、总结
本文共4540个字,阅读大约需要15分钟,欢迎指正!
Part1前言
Part2用 Python 计算文本相似度
1编辑距离
S1 = '今天中午吃什么'
S2 = '今天中午什么都不想吃'
# 导入模块
from distance import levenshtein
# 计算编辑距离
levenshtein('今天中午吃什么','今天中午什么都不想吃')
# 得到:5
fuzzywuzzy
是其中非常好用的一个,支持简单匹配、非完全匹配、忽略顺序匹配等多种计算文本相似度的方式。下面是简单使用 fuzzywuzzy 模块的代码:# 导入 fuzzywuzzy 中计算文本相似度的方法
from fuzzywuzzy import fuzz
# 文本相似度分数从 0 到 100,数值越大,相似度越高
# 1.简单匹配:默认方式计算两个字符串的相似度。
fuzz.ratio('今天中午吃什么','今天中午什么都不想吃')
# 得到: 71
# 2.非完全匹配,当一个字符串和另一个字符串的某一部分
# 相似度较高时,可以得到较高的结果
fuzz.partial_ratio('今天中午吃什么', '中午了,该去吃饭了。今天中午吃什么呢?反正我吃什么都行。')
# 得到:100
# 3.忽略顺序匹配:顾名思义,倒装句的死敌;但是
# 词语之间需要使用空格分隔,最好先分词再计算
fuzz.token_sort_ratio('今天中午 吃什么', '吃什么 今天中午')
# 得到:100
# 4.去重子集匹配,使用前最好先分词,原因同上
fuzz.token_set_ratio('今天 中午 吃什么','今天 中午 中午 中午 吃什么')
# 得到:100
2杰卡德距离
去掉 junk 字符。什么是 junk 字符呢?就是我们不希望计入匹配的字词,可以自定义。 计算两字符串之间所有匹配片段的长度之和 M,则杰卡德距离的计算公式就是:
S1 = '今天中午吃什么'
S2 = '今天中午什么都不想吃'
difflib
即可计算杰卡德系数,也可以说是基于杰卡德系数计算文本相似度,代码如下:# 导入模块
from difflib import SequenceMatcher
# 计算相似度
SequenceMatcher(None, '今天中午吃什么','今天中午什么都不想吃').quick_ratio()
# 得到:0.8235294117647058
3余弦相似度
# 导入计算文本相似度的类
from simtext import similarity
# 定义文本相似度对象
sim = similarity()
# 计算文本相似度
res = sim.compute('今天中午吃什么','今天中午什么都不想吃')
res
4TF-IDF
# 导入 sklearn 中可以将文本进行 tf-idf 处理并转化为向量的方法
from sklearn.feature_extraction.text import TfidfVectorizer
# 导入数学计算方法
import numpy as np
from scipy.linalg import norm
# 导入分词工具
import jieba
# 定义计算相似度的方法
def tfidf_similarity(s1, s2):
def add_space(s):
# 分词,词语间使用空格分隔
return ' '.join(jieba.lcut(s))
# 将词语中间加入空格,方便转为矩阵
s1, s2 = add_space(s1), add_space(s2)
# 转化为矩阵
cv = TfidfVectorizer(tokenizer=lambda s: s.split(' '))
corpus = [s1, s2]
vectors = cv.fit_transform(corpus).toarray()
# 计算TF-IDF系数
return np.dot(vectors[0], vectors[1]) / (norm(vectors[0]) * norm(vectors[1]))
s1 = '今天中午吃什么'
s2 = '今天中午什么都不想吃'
print(tfidf_similarity(s1, s2))
# 得到:0.7092972666062738,换算为百分制就是 71
5基于近义词
S1 = '尽管步履维艰,我们依然不会放弃'
S2 = '就算困难重重,咱们仍旧不能退出'
# 使用 synonyms 计算文本相似度,基于近义词
import synonyms
print(synonyms.compare(S1, S2, seg=True)) # 得到:0.659
# 编辑距离法
print(fuzz.ratio(S1, S2)) # 得到:20
# 杰卡德系数法
print(SequenceMatcher(None, S1,S2).quick_ratio()) # 得到: 0.2
# 列出一个词语的近义词和相似度,基于语料库
synonyms.display('转发')
# 得到:
'转发'近义词:
1. 转发:1.0
2. 留言:0.62906045
3. 跟帖:0.5896571
4. 回帖:0.58484876
5. 转贴:0.58105844
6. 删帖:0.57204753
7. 刷屏:0.5678909
8. 朋友圈:0.56369257
9. 登出:0.5478899
10. 截取:0.52591866
# 分词并列出词语的词性
synonyms.seg('尽管步履维艰,我们依然不会放弃')
(['尽管', '步履维艰', ',', '我们', '依然', '不会', '放弃'],
['c', 'l', 'x', 'r', 'd', 'v', 'v'])
Part3总结
我们将在数据治理板块中推出一系列原创推文,帮助读者搭建一个完整的社科研究数据治理软硬件体系。该板块将涉及以下几个模块(点击标题即可跳转至相应合集):
星标⭐我们不迷路!想要文章及时到,文末“在看”少不了!
点击搜索你感兴趣的内容吧
往期推荐
数据Seminar
这里是大数据、分析技术与学术研究的三叉路口
文 | 《社科领域大数据治理实务手册》
欢迎扫描👇二维码添加关注